Skip to content

技术栈-框架-SpringBoot的使用-面试题

后面再整理一下,和之前自己的面试煎熬内容一起整理一下

二、基础内容

2.1 配置文件格式

Spring Boot的配置文件有哪几种格式?核心配置文件有哪些?

ad-tldr
title: 说明
collapse: open 或 closed


Spring Boot支持以下几种格式的配置文件:

1. **properties文件**:传统的Java属性文件,使用`.properties`后缀,文件格式是键值对形式,文件名通常是`application.properties`或`bootstrap.properties`。
2. **YAML文件**:更为现代的配置文件格式,使用`.yml`或`.yaml`后缀,使用缩进来表示层级关系,文件名通常是`application.yml`或`bootstrap.yml`。

核心配置文件通常是指:

1. **application.properties** 或 **application.yml**:这是Spring Boot的主要配置文件。在此文件中定义的属性可以应用于你的Spring Boot应用程序的任何部分。
2. **bootstrap.properties** 或 **bootstrap.yml**:当使用Spring Cloud Config时,这些文件用于外部配置的早期加载。

这些文件可以放在以下位置:

- 项目的根目录。
- `/config` 子目录。
- 类路径的根目录 (`/resources` 或 `/src/main/resources`)。
- 类路径的`/config` 包。

Spring Boot会按照特定的顺序来加载这些配置文件,以确保属性的正确覆盖和加载。

上面提到的  bootstrap 配置文件是属于 SpringCloud 环境,需要引入相关依赖;

在 SpringCloud 环境中,**bootstrap配置文件会优先于application配置文件加载**,它主要用于从额外的资源来加载配置参数,通常用来加载外部配置,如Spring Cloud用于加载配置中心的配置参数,也可以用来定义系统不会被改变的参数,它们默认不能被本地相同的配置所覆盖。

2.2 配置加载顺序

Spring Boot配置加载顺序是怎样的?

ad-tldr
title: 说明
collapse: open 或 closed


Spring Boot的配置加载顺序设计用于支持不同的配置需求和环境,从而允许在运行时覆盖应用程序的配置。以下是Spring Boot配置加载的顺序,从高优先级到低优先级:

1. **开发者工具的配置属性** (如果使用Spring Boot的开发者工具)。
2. **命令行参数** (`java -jar myproject.jar --name="Spring"`).
3. **来自`SPRING_APPLICATION_JSON`的属性** (环境变量或系统属性中的内联JSON)。
4. **`ServletConfig`初始化参数**。
5. **`ServletContext`初始化参数**。
6. **`java:comp/env`里的JNDI属性**。
7. **Java系统属性** (`System.getProperties()`).
8. **操作系统环境变量**。
9. *   只有在random. 里定义的随机属性。
10. **应用程序在打包时提供的JAR文件外的`application.properties`或`application.yml`文件**。
11. **应用程序打包在JAR内的`application.properties`或`application.yml`文件**。
12. **通过`@PropertySource`注解在`@Configuration`类上定义的属性**。
13. **默认属性** (通过`SpringApplication.setDefaultProperties`指定)。

在这个顺序中,较高的属性将覆盖较低的属性。这就是为什么命令行参数可以覆盖`application.properties`中的属性,因为命令行参数的优先级更高。

辅助理解:

**命令行 > 外部配置 > 内部配置**

重点配置来源及其优先级(从高到低):

- 命令行参数
- 外部Jar包配置文件
- 应用程序配置文件
- 默认属性

1. **命令行参数**:
    - 最直接的覆盖方式,适用于临时改变某些配置。
    - 例如:`java -jar app.jar --server.port=9090`
2. **外部配置文件**(外部`application.properties`或`application.yml`):
    - 这包括位于应用程序jar文件同级目录下的配置文件,或通过`--spring.config.location`指定的路径。
    - 这些配置文件优先于应用程序内部的配置文件。
3. **应用程序内部配置文件**(内部`application.properties`或`application.yml`):
    - 打包在应用程序jar内的配置文件。
    - 对于默认配置或开发时的配置非常有用。
4. **`@PropertySource`注解**:
    - 可以在Spring `@Configuration`类上指定额外的配置源。
    - 适用于更细粒度的配置或环境特定配置。
5. **默认属性**:
    - 通过编码方式设置的默认配置,通常在应用启动类中设置。
    - 适用于定义全局的回退配置。

2.3 常用的日志框架

Spring Boot支持哪些日志框架?

ad-tldr
title: 题目解析
collapse: open 或 closed


Spring Boot支持以下日志框架:

1. **Logback** (默认): Spring Boot默认使用Logback作为日志框架。
2. **Log4j2**: 通过排除Spring Boot的默认日志依赖并包含log4j2的依赖,可以使用Log4j2。
3. **JUL (Java Util Logging)**: Spring Boot也支持JUL,但通常需要额外的配置来整合。
4. **SLF4J**: Spring Boot使用SLF4J作为日志抽象层,你可以将其与上述任何日志实现配合使用。

为了使用特定的日志框架,你需要在项目的依赖管理文件中(如pom.xml或build.gradle)包含对应的依赖,并适当配置日志框架的配置文件(如logback-spring.xml, log4j2.xml等)。


同时需要注意的是:目前Apache已经宣布停止对Log4j 1.x的更新和支持,并且 Log4j 出现了严重的安全漏洞(如Log4Shell);因此目前 SpringBoot 也不支持  Log4j 版本;我们在使用的时候需要选择 **Log4j2** 而不是 Log4j。
title: 配置示例
collapse: open 或 closed

// Spring Boot配置示例,指定日志框架为Logback
spring:
  main:
    web-application-type: none
logging:
  config: classpath:logback-spring.xml

2.4 日志属性配置

Spring Boot如何配置日志?

在Spring Boot中配置日志的关键点主要涉及到日志级别的设置、日志输出的定位以及日志的格式自定义。这些配置项可以通过application.propertiesapplication.yml文件来灵活设置。

下面是关于这些配置的重点整理:

  1. 设置日志级别
  • 目的:控制日志的输出粒度,例如,在开发过程中可能需要更详细的日志(如DEBUGTRACE级别),而在生产环境中可能只需INFOWARN级别的日志。
  • 配置方式logging.level.<logger-name>=<level>
  • 示例
# 设置根日志记录器的日志级别为WARN,这意味着只有WARN级别以上的日志消息(WARN, ERROR, FATAL)会被记录。
logging.level.root=WARN
# 设置org.springframework.web包下的日志记录器的日志级别为DEBUG,这将记录DEBUG级别及以上的日志消息,适用于调试Spring Web相关的行为。
logging.level.org.springframework.web=DEBUG
# 设置com.mycom包的日志级别
logging.level.com.mycompany=INFO
  1. 日志文件配置
  • 目的:指定日志输出的文件名和路径,便于日志的查阅和管理。
  • 配置项
    • logging.file.name: 指定日志文件的全名,包括路径。
    • logging.file.path: 指定日志文件存放的目录,日志文件名由Spring Boot自动生成。
  • 示例
# 配置日志文件的名称为myapp.log。如果设置了logging.file.name,日志将被写入指定的文件中,而不是控制台。
logging.file.name=myapp.log
# 或者
# 或者,可以单独设置日志文件存储的路径。这里设置日志文件存储在`/var/log`目录下。
logging.file.path=/var/log
# 注意:当同时设置logging.file.name和logging.file.path时,日志文件(这里是myapp.log)将被创建在指定的路径下(/var/log/myapp.log)。
  1. 日志格式配置
  • 目的:自定义日志输出的格式,以满足不同的可读性和信息需求。
  • 配置项
    • logging.pattern.console: 控制台日志的格式。
    • logging.pattern.file: 文件日志的格式。
  • 示例
# 设置控制台输出的日志格式。%d{yyyy-MM-dd HH:mm:ss}是日期时间的格式,%msg是日志消息,%n是新行。
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} - %msg%n
# 设置写入文件的日志格式。包含了日期时间、线程名、日志级别、日志记录器名和日志消息。 
# [%thread]显示线程名,%-5level是左对齐的日志级别,%logger{36}是日志记录器的名字,最多36个字符,%msg是日志消息。
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
  1. 使用logback-spring.xmllog4j2-spring.xml文件
  • 目的:对于更复杂的日志配置需求,如日志归档、异步日志记录等,可以通过这些XML配置文件进行详细设置。
  • 注意:确保将这些配置文件放置在src/main/resources目录下,Spring Boot会自动识别并加载它们。

配置重点

  • 灵活性:Spring Boot允许你通过简单的属性配置来快速设置日志级别和输出位置,同时也支持通过XML配置文件进行更复杂的日志管理配置。
  • 日志级别的合理设置:合理设置日志级别可以帮助开发者在开发、测试和生产环境中更有效地获取所需的日志信息。
  • 日志格式化:自定义日志格式可以提高日志的可读性,使得日志信息更加直观、易于理解。
  • 高级配置:对于高级用户,使用XML配置文件可以实现更高级的日志管理功能,如滚动归档、日志清理策略等。

后续这里待整理一下 to be contined....

// application.properties中配置日志级别和日志文件路径的示例
logging.level.root=INFO 
logging.level.org.springframework.web=DEBUG
logging.level.com.yourpackage=TRACE

logging.file.name=app.log
logging.file.path=/var/log

在Spring Boot中,你可以通过application.propertiesapplication.yml文件来配置日志。

以下是一些常用的日志配置选项:

  1. 设置日志级别:
    • 通过logging.level.<logger-name>=<level>设置特定日志记录器的日志级别。
    • 日志级别包括:TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF
  2. 日志文件配置:
    • logging.file.name: 设置日志文件名,会在当前目录生成日志文件。
    • logging.file.path: 设置日志文件路径,日志文件会在指定的目录生成。
  3. 日志格式配置:
    • logging.pattern.console: 设置控制台输出的日志格式。
    • logging.pattern.file: 设置写入文件的日志格式。
  4. 日志归档:
    • 如果使用Logback,默认会进行日志归档(每天生成一个日志文件,过期删除等)。
    • 详细的归档策略可以通过Logback的logback-spring.xml配置文件来设置。
  5. 使用logback-spring.xmllog4j2-spring.xml文件:
    • 对于更复杂的配置,如日志归档、异步记录等,可以使用XML配置文件。
    • 将这些文件放在src/main/resources目录下,Spring Boot会自动加载它们。

通过这些配置,你可以根据需要灵活地设置日志级别、格式、输出位置等。

自动配置

Spring Boot的自动配置原理是什么?
// 示例:使用自动配置的注解
@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

Spring Boot的自动配置原理基于以下几个核心概念:

  1. @SpringBootApplication注解:

    • 这是一个便利注解,相当于同时使用了@Configuration@EnableAutoConfiguration@ComponentScan
    • @EnableAutoConfiguration是自动配置的关键,它告诉Spring Boot开始加载基于类路径下的内容、其他bean和各种属性设置的自动配置。
  2. 条件注解 (@Conditional...):

    • Spring Boot自动配置是条件化的,意味着自动配置类会根据环境和classpath下的类的存在与否应用。
    • 这些条件可以是类的存在、bean的存在、属性的存在或匹配等。
  3. spring.factories文件:

    • Spring Boot利用spring.factories文件来加载自动配置候选者。
    • 在这个文件中,通过org.springframework.boot.autoconfigure.EnableAutoConfiguration键指定自动配置类。
  4. 自动配置类 (@Configuration):

    • 自动配置类是常规的Spring配置类,通常用@Configuration标记,并通过条件注解进行条件化配置。
    • 这些类通过@Bean方法提供了默认的bean定义,并且通常是通过@ConditionalOn...注解来条件化的。

原理简述:

  • 当Spring应用启动时,@EnableAutoConfiguration注解触发了一个自动配置的过程。
  • 这个过程从classpath中的META-INF/spring.factories文件中读取并加载所有可用的自动配置类。
  • 每个自动配置类可以根据条件(比如classpath中是否存在某个类、是否存在某个bean、某个属性是否有特定的值等)决定配置是否应用。
  • 如果条件满足,相应的配置被应用(比如创建一个bean、添加属性值等)。

这种自动配置机制大大简化了Spring应用的配置,尤其是在构建独立的、生产级别的Spring应用时。


自动装配原理:

Spring Boot的自动配置原理是通过条件化配置和Spring的注解机制来实现的,当应用启动时,Spring Boot会自动扫描应用中的依赖,根据依赖自动配置Spring应用程序上下文,以便开箱即用。

常用注解

SpringBoot 有哪些条件注解,这些注解怎么使用的
// 示例: 使用条件注解

@Configuration
@ConditionalOnClass({ExampleService.class})
public class ExampleAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public ExampleService exampleService() {
        return new ExampleServiceImpl();
    }

    @Bean
    @ConditionalOnProperty(name = "example.enabled", havingValue = "true", matchIfMissing = true)
    public ExampleFeature exampleFeature() {
        return new ExampleFeature();
    }
    
    @Bean
    @ConditionalOnExpression("${example.expression:true}")
    public ExampleComponent exampleComponent() {
        return new ExampleComponent();
    }
}

Spring Boot提供了多种条件注解来控制配置的条件化创建,以下是一些常用的条件注解及其用法:

  1. @ConditionalOnClass / @ConditionalOnMissingClass:
    • 根据类路径上是否存在某个类来决定是否创建Bean。
  2. @ConditionalOnBean / @ConditionalOnMissingBean:
    • 根据上下文中是否存在(或缺失)某个Bean来决定是否创建Bean。
  3. @ConditionalOnProperty:
    • 根据配置文件中是否存在某个属性,或该属性的值是否符合预期来决定是否创建Bean。
  4. @ConditionalOnResource:
    • 根据类路径上是否存在某个资源来决定是否创建Bean。
  5. @ConditionalOnExpression:
    • 根据SpEL表达式的计算结果来决定是否创建Bean。
  6. @ConditionalOnWebApplication / @ConditionalOnNotWebApplication:
    • 根据应用是否是Web应用来决定是否创建Bean。
  7. @ConditionalOnJndi:
    • 根据JNDI位置的存在与否来决定是否创建Bean。

这些注解通常用在自动配置类中,使得Bean的创建可以根据不同的环境或配置动态地进行。

上面这写是跟 @Conditional 的基础上组合使用的,介绍一下它:

  • @Conditional
  • 这是Spring4.0添加的新注解,用来标识一个Spring Bean或者Configuration配置文件,当满足指定的条件才开启配置。

Spring Boot官方的启动器命名规范是?
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-*</artifactId>
    <version>...</version>
</dependency>

Spring Boot官方的启动器(starters)遵循以下命名规范:

  • 基本格式: spring-boot-starter-XYZ
  • XYZ: 描述启动器的功能,例如 web, data-jpa, security 等。
  • 版本号: 根据项目需求指定合适的Spring Boot版本。

Spring Boot官方的启动器都是以spring-boot-starter--* 命名的,* 代表了一个特定的应用类型。

第三方的启动器不能以spring-boot开头命名,它们都被Spring Boot官方保留。

一般一个第三方的应该这样命名,像mybatis的 mybatis-spring-boot-starter。.


Spring Boot的starter是什么?
// Spring Boot Starter Dependency Example
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Spring Boot Starter是一种依赖管理器,它简化了Spring应用程序的依赖配置。

每个Starter都是一个Maven项目,它封装了特定于某一功能(如Web开发、数据访问等)的依赖关系。使用Starter时,你只需声明单个依赖项,Spring Boot就会为你提供该功能所需的所有依赖项。这极大地简化了项目的构建配置,并有助于避免版本冲突和依赖性问题。

怎么自定义一个 starter
// 1. 创建一个新的Maven项目作为自定义Starter

// 2. 在pom.xml中添加Spring Boot的parent和基本依赖
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.x.x.RELEASE</version>
</parent>

<dependencies>
    // 添加所需功能的依赖
</dependencies>

// 3. 创建自动配置类,使用@Configuration和@ConditionalOn...注解
@Configuration
@ConditionalOnClass({ YourService.class })
@ConditionalOnProperty(prefix = "your.starter", name = "enabled", havingValue = "true", matchIfMissing = true)
public class YourStarterAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public YourService yourService() {
        return new YourServiceImpl();
    }
}

// 4. 在resources/META-INF下创建spring.factories文件,声明自动配置类
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
your.package.YourStarterAutoConfiguration

步骤:

  1. 创建项目: 创建一个Maven项目作为你的Starter。
  2. 添加依赖: 在pom.xml中声明Spring Boot的parent依赖,和其他所需的依赖。
  3. 编写自动配置: 创建配置类,使用@Configuration注解,通过@ConditionalOn...注解确保只在满足特定条件时才应用配置。
  4. 声明配置: 在resources/META-INF/spring.factories文件中,声明你的自动配置类,以便Spring Boot在启动时自动发现它。

内嵌容器

Spring Boot支持哪几种内嵌容器?

Spring支特的内嵌式容器有:Tomcat、Jetty、Undertow

默认的内嵌式容器是:Tomcat。

配置加载

Spring Boot怎么兼容老Spring项目?

答案是可以兼容,可以使用 @ImportResource注解 来导入之前是 Spring 项目的配置文件

@Configuration
@ImportResource({ "classpath*:legacy-spring-context.xml" })
public class LegacyConfig {
}
  1. 创建一个新的Spring Boot项目: 初始化一个标准的Spring Boot项目结构。
  2. 集成老项目的配置:
    • 使用@ImportResource注解导入老Spring项目的XML配置文件。
    • 如果老项目使用的是Java配置,可以直接在Spring Boot的配置类中导入。
  3. 逐步迁移:
    • 将老项目的代码和资源文件复制到Spring Boot项目中。
    • 逐步替换老项目中的Spring功能实现,如数据源配置、事务管理等,使用Spring Boot的自动配置功能。
  4. 测试和调优:
    • 仔细测试整合后的应用,确保功能正常。
    • 根据需要调优Spring Boot的配置,比如日志级别、数据库连接等。